﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using SemPlayGen.DataModel;
using VDS.RDF;
using VDS.RDF.Parsing;
using VDS.RDF.Writing;
using SemPlayGen.DataModel.RefactoredObjects;
using VDS.RDF.Query;

namespace SemPlayGen.Logic
{
    public static class Semantics
    {
        public static void InsertToRDF(Songs song)
        {
            IGraph graph = new Graph();

            UriNode ns0 = graph.CreateUriNode(new Uri("http://SemPlayGen.com"));
            UriNode MusicType = graph.CreateUriNode(new Uri("http://SemPlayGen.com/MusicType"));
            UriNode Genre = graph.CreateUriNode(new Uri("http://SemPlayGen.com/Genre"));
            UriNode ArtistType = graph.CreateUriNode(new Uri("http://SemPlayGen.com/ArtistType"));
            UriNode Lyrics = graph.CreateUriNode(new Uri("http://SemPlayGen.com/Lyrics"));
            UriNode Signal = graph.CreateUriNode(new Uri("http://SemPlayGen.com/Signal"));
            UriNode SongName = graph.CreateUriNode(new Uri("http://SemPlayGen.com/SongName"));
            UriNode ArtistName = graph.CreateUriNode(new Uri("http://SemPlayGen.com/ArtistName"));

            UriNode ID = graph.CreateUriNode(new Uri("http://SemPlayGen.com/ID"));
            UriNode ID_node = graph.CreateUriNode(new Uri("http://SemPlayGen.com/" + song.ID));

            //creating graph
            graph.Assert(new Triple(ns0, ID, ID_node));
            graph.Assert(new Triple(ID_node, MusicType, graph.CreateLiteralNode(song.MusicTypes.Name)));
            graph.Assert(new Triple(ID_node, ArtistType, graph.CreateLiteralNode(song.ArtistTypes.Name)));
            graph.Assert(new Triple(ID_node, Genre, graph.CreateLiteralNode(song.Genres.Name)));
            graph.Assert(new Triple(ID_node, Lyrics, graph.CreateLiteralNode(song.HasLyrics.ToString())));
            graph.Assert(new Triple(ID_node, Signal, graph.CreateLiteralNode(song.Signals.Name)));
            graph.Assert(new Triple(ID_node, SongName, graph.CreateLiteralNode(song.SongName)));
            graph.Assert(new Triple(ID_node, ArtistName, graph.CreateLiteralNode(song.ArtistName)));

            graph.NamespaceMap.AddNamespace("Songs", new Uri("http://SemPlayGen.com"));
            UriNode qname = graph.CreateUriNode("Songs:demo");


            //****************************************************************************************
            //****************************************************************************************
            //****************************************************************************************

            Graph g2 = new Graph();
            string Songs_nt = HttpContext.Current.Request.MapPath("~") + @"\SemanticFiles\Songs.nt";
            string Songs_rdf = HttpContext.Current.Request.MapPath("~") + @"\SemanticFiles\Songs.rdf";
            string Songs_ttl = HttpContext.Current.Request.MapPath("~") + @"\SemanticFiles\Songs.ttl";

            try
            {
                //load original graph from filename
                NTriplesParser ntparser = new NTriplesParser();
                ntparser.Load(g2, Songs_nt);

                //merge graph with temp_graph
                graph.Merge(g2);
            }
            catch(Exception ex)
            {
            }

            //create semantic files
            NTriplesWriter ntwriter = new NTriplesWriter();
            ntwriter.Save(graph, Songs_nt);

            //RdfXmlTreeWriter rdfxmlwriter = new RdfXmlTreeWriter();
            FastRdfXmlWriter rdfxmlwriter = new FastRdfXmlWriter();
            rdfxmlwriter.Save(graph, Songs_rdf);

            TurtleWriter writer = new TurtleWriter();
            writer.Save(graph, Songs_ttl);
        }




        public static IList<SongsRefactored> GeneratePlaylist(int playlistLength, string artistType, string musicType, string genre)
        {
            IList<SongsRefactored> songsList = new List<SongsRefactored>();

            Graph g = new Graph();
            TripleStore t_store = new TripleStore();
            FileLoader.Load(g, HttpContext.Current.Server.MapPath("~") + @"\SemanticFiles\Songs.rdf");

            try
            {
                t_store.Add(g);
            }
            catch { }

            string query = ""
                        + " SELECT ?artistName ?songName ?genre ?hasLyrics"
                        + " WHERE {"
                        + (!String.IsNullOrEmpty(artistType) ? " ?a <http://semplaygen.com/ArtistType> \"" + artistType + "\" . " : "")
                        + (!String.IsNullOrEmpty(musicType) ? " ?a <http://semplaygen.com/MusicType> \"" + musicType + "\" . " : "")
                        + (!String.IsNullOrEmpty(genre) ? " ?a <http://semplaygen.com/Genre> \"" + genre + "\" . " : "")
                        + " ?a <http://semplaygen.com/ArtistName> ?artistName"
                        + " . ?a <http://semplaygen.com/SongName> ?songName"
                        + " . ?a <http://semplaygen.com/Genre> ?genre"
                        + " . ?a <http://semplaygen.com/Lyrics> ?hasLyrics"
                        + " }";
            SparqlResultSet resultSet = (SparqlResultSet)t_store.ExecuteQuery(query);


            int i = 0;
            foreach (SparqlResult r in resultSet)
            {
                if (i == playlistLength)
                    break;

                string artistName, songName, genre_, hasLyrics;
                artistName = r["artistName"].ToString();
                songName = r["songName"].ToString();
                genre_ = r["genre"].ToString();
                hasLyrics = r["hasLyrics"].ToString() == "True" ? "Да" : "Не";
                
                songsList.Add(new SongsRefactored(artistName, songName, genre_, hasLyrics));
                i++;
            }

            return songsList.OrderBy(x => x.ArtistName).ToList();
        }



        public static void SynchronizeWithDB(IList<Songs> songsDataSet)
        {
            string Songs_nt = HttpContext.Current.Request.MapPath("~") + @"\SemanticFiles\Songs.nt";
            string Songs_rdf = HttpContext.Current.Request.MapPath("~") + @"\SemanticFiles\Songs.rdf";
            string Songs_ttl = HttpContext.Current.Request.MapPath("~") + @"\SemanticFiles\Songs.ttl";

            System.IO.File.Delete(Songs_nt);
            System.IO.File.Delete(Songs_rdf);
            System.IO.File.Delete(Songs_ttl);

            foreach (Songs song in songsDataSet)
            {
                InsertToRDF(song);
            }
        }
    }
}